package ec.fugu.util;

import java.io.IOException;
import java.util.Hashtable;

import com.roadtrack.views.UbikoBlackBerry;
import com.roadtrack.vo.bussiness.UbikoConstants;

import net.rim.device.api.i18n.ResourceBundle;
import assets.res.UbikoResource;
import ec.fugu.amf.ASObject;
import ec.fugu.amf.AmfBody;
import ec.fugu.amf.AmfClient;
import ec.fugu.amf.AmfMessage;

/**
 * NetworkThread
 * 
 * This is just a Thread which the Main UI must wait for.
 * 
 * In most applications this will be a networking Thread
 * so this sample has been designed to simulate that.
 * It is created with a URL and returns a byte array.
 *
 */

public class NetworkLoopThread extends Thread  implements UbikoResource{

	private static ResourceBundle _res = ResourceBundle.getBundle(BUNDLE_ID, BUNDLE_NAME);
	private ObserverInterface _ourObserver;
    private AmfClient _client = null;
    private String _method = null;
    private Object[] _params = null;
    private AmfMessage _response;
    private boolean _stopRequest = false;
    private boolean _needAuth = false;
    private long _startTime=0;
    private long _finishTime=0;
    private int _timeout=3000;
    private int _updateInterval=2000;
    private String _status=null; 
    
    /**
     * Create a networkThread
     * @param client AmfClient to use in the Thread
     * @param method Remote method to be invoked
     * @param params Params of the Remote Method
     * @param timeout Timeout of the request
     * @param observer 
     */
    public NetworkLoopThread(AmfClient client, String method, Object[] params, int timeout,ObserverInterface observer) {
        super();
        _client = client;
        _ourObserver = observer;
        _method = method;
        _params = params;
        _timeout = timeout;
    }

    public NetworkLoopThread(AmfClient client, String method, Object[] params, int timeout,ObserverInterface observer, boolean needAuth) {
        super();
        _client = client;
        _ourObserver = observer;
        _method = method;
        _params = params;
        _timeout = timeout;
        _needAuth = needAuth;
    }

    /**
     * stop is called if the processing should not continue.
     */
    public void stop() {
        // Tell our observer
        observerError(ObserverInterface.CANCELLED, _res.getString(CANCELED));
        _stopRequest = true; // Will no longer tell Observer anything
        this.interrupt(); // Give our Thread a kick
    }

    private void observerStatusUpdate(final int status, final String statusString) {
        if ( !_stopRequest ) {
            _ourObserver.processStatusUpdate(status, statusString);
        }
    }

    private void observerError(int errorCode, String errorMessage) {
        if ( !_stopRequest ) {
            _ourObserver.processError(errorCode, errorMessage);
        }
    }

    private void observerResponse(AmfMessage reply) {
        if ( !_stopRequest ) {
            _ourObserver.processResponse(reply);
        }
    }

    /**
     * Process the long running or blocking operation in this Thread
     * Update the Observer as required using
     * - processStatus, whenever desired
     * and then one of:
     * - processError, if there was a problem
     * - processResponse, if the data was obtained OK
     */
    public void run () {
        boolean willFail = false; // false - will finshed OK, true - will fail!
        _startTime = System.currentTimeMillis();
        _finishTime = _startTime + _timeout;

        observerStatusUpdate(1, "Started"); // Tell user we have started
        try {
        	int counter = 0;
        	while(System.currentTimeMillis()< _finishTime){
    			_client.resetRequest();
    			if(_needAuth && UbikoBlackBerry.hasCredentials()){
        			Hashtable credentials = UbikoBlackBerry.getCredentials();
            		_client.setCredentials(credentials.get("username").toString(), credentials.get("password").toString());
    			} else if(_needAuth && !UbikoBlackBerry.hasCredentials()){
    				throw new IOException(_res.getString(MISSINGCREDENTIAL));
    			}
    			_client.sendRequest(_method, _params);
    			_response=_client.getResponse();
				Object[] array = (Object[])((AmfBody)_response.getBodies().firstElement()).getData();
				_status = ((ASObject)array[0]).get("Status").toString();
				if(!_status.equalsIgnoreCase(UbikoConstants.StatusNew)){
					break;
				}
                try {
                    Thread.sleep(_updateInterval);
                } catch (InterruptedException e) {
                }
            	counter++;
            	observerStatusUpdate(counter, "Procesando ... "+counter);
        	}
	        observerStatusUpdate(counter, "Finished"); // Tell Observer we have finished
		} catch (IOException e) {
			System.err.println("NetworkThread-run IOException: " + e.getMessage());
			e.printStackTrace();
			willFail = true;
		}
        _finishTime = System.currentTimeMillis();
        //  Did we finish OK or badly
        if ( willFail ) {
            observerError(ObserverInterface.ERROR, "Failed");
        } else {
            observerResponse(_response);
        }

        // Make sure we do nothing else
        _stopRequest = true;
        _ourObserver = null;
    }
}